import dayjs from 'dayjs'
import { ElMessage, ElMessageBox, ElNotification } from 'element-plus'

/**
 * 通用工具函数
 */

/**
 * 格式化日期时间
 * @param {string|Date} date - 日期
 * @param {string} format - 格式
 * @returns {string}
 */
export const formatDateTime = (date, format = 'YYYY-MM-DD HH:mm:ss') => {
  if (!date) return ''
  return dayjs(date).format(format)
}

/**
 * 格式化日期
 * @param {string|Date} date - 日期
 * @returns {string}
 */
export const formatDate = date => {
  return formatDateTime(date, 'YYYY-MM-DD')
}

/**
 * 格式化时间
 * @param {string|Date} date - 日期
 * @returns {string}
 */
export const formatTime = date => {
  return formatDateTime(date, 'HH:mm:ss')
}

/**
 * 格式化相对时间
 * @param {string|Date} date - 日期
 * @returns {string}
 */
export const formatRelativeTime = date => {
  if (!date) return ''
  const now = dayjs()
  const target = dayjs(date)
  const diff = now.diff(target, 'second')

  if (diff < 60) {
    return '刚刚'
  } else if (diff < 3600) {
    return `${Math.floor(diff / 60)}分钟前`
  } else if (diff < 86400) {
    return `${Math.floor(diff / 3600)}小时前`
  } else if (diff < 2592000) {
    return `${Math.floor(diff / 86400)}天前`
  } else {
    return formatDate(date)
  }
}

/**
 * 格式化文件大小
 * @param {number} bytes - 字节数
 * @param {number} decimals - 小数位数
 * @returns {string}
 */
export const formatFileSize = (bytes, decimals = 2) => {
  if (bytes === 0) return '0 Bytes'

  const k = 1024
  const dm = decimals < 0 ? 0 : decimals
  const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']

  const i = Math.floor(Math.log(bytes) / Math.log(k))

  return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i]
}

/**
 * 格式化数字
 * @param {number} num - 数字
 * @param {number} decimals - 小数位数
 * @returns {string}
 */
export const formatNumber = (num, decimals = 0) => {
  if (num === null || num === undefined) return '0'
  return Number(num).toLocaleString('zh-CN', {
    minimumFractionDigits: decimals,
    maximumFractionDigits: decimals
  })
}

/**
 * 格式化百分比
 * @param {number} value - 值
 * @param {number} total - 总数
 * @param {number} decimals - 小数位数
 * @returns {string}
 */
export const formatPercentage = (value, total, decimals = 1) => {
  if (!total || total === 0) return '0%'
  const percentage = (value / total) * 100
  return `${percentage.toFixed(decimals)}%`
}

/**
 * 格式化持续时间
 * @param {number} seconds - 秒数
 * @returns {string}
 */
export const formatDuration = seconds => {
  if (!seconds || seconds < 0) return '00:00:00'

  const hours = Math.floor(seconds / 3600)
  const minutes = Math.floor((seconds % 3600) / 60)
  const secs = Math.floor(seconds % 60)

  return `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`
}

/**
 * 格式化比特率
 * @param {number} bps - 比特率（bps）
 * @returns {string}
 */
export const formatBitrate = bps => {
  if (!bps || bps === 0) return '0 bps'

  const units = ['bps', 'Kbps', 'Mbps', 'Gbps']
  let index = 0
  let value = bps

  while (value >= 1000 && index < units.length - 1) {
    value /= 1000
    index++
  }

  return `${value.toFixed(1)} ${units[index]}`
}

/**
 * 深拷贝对象
 * @param {any} obj - 要拷贝的对象
 * @returns {any}
 */
export const deepClone = obj => {
  if (obj === null || typeof obj !== 'object') return obj
  if (obj instanceof Date) return new Date(obj.getTime())
  if (obj instanceof Array) return obj.map(item => deepClone(item))
  if (typeof obj === 'object') {
    const clonedObj = {}
    for (const key in obj) {
      if (Object.prototype.hasOwnProperty.call(obj, key)) {
        clonedObj[key] = deepClone(obj[key])
      }
    }
    return clonedObj
  }
}

/**
 * 防抖函数
 * @param {Function} func - 要防抖的函数
 * @param {number} wait - 等待时间
 * @param {boolean} immediate - 是否立即执行
 * @returns {Function}
 */
export const debounce = (func, wait, immediate = false) => {
  let timeout
  return function executedFunction(...args) {
    const later = () => {
      timeout = null
      if (!immediate) func(...args)
    }
    const callNow = immediate && !timeout
    clearTimeout(timeout)
    timeout = setTimeout(later, wait)
    if (callNow) func(...args)
  }
}

/**
 * 节流函数
 * @param {Function} func - 要节流的函数
 * @param {number} limit - 限制时间
 * @returns {Function}
 */
export const throttle = (func, limit) => {
  let inThrottle
  return function (...args) {
    if (!inThrottle) {
      func.apply(this, args)
      inThrottle = true
      setTimeout(() => (inThrottle = false), limit)
    }
  }
}

/**
 * 生成UUID
 * @returns {string}
 */
export const generateUUID = () => {
  return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
    const r = (Math.random() * 16) | 0
    const v = c === 'x' ? r : (r & 0x3) | 0x8
    return v.toString(16)
  })
}

/**
 * 生成随机字符串
 * @param {number} length - 长度
 * @returns {string}
 */
export const generateRandomString = (length = 8) => {
  const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
  let result = ''
  for (let i = 0; i < length; i++) {
    result += chars.charAt(Math.floor(Math.random() * chars.length))
  }
  return result
}

/**
 * 验证IP地址
 * @param {string} ip - IP地址
 * @returns {boolean}
 */
export const validateIP = ip => {
  const ipRegex =
    /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/
  return ipRegex.test(ip)
}

/**
 * 验证端口号
 * @param {number|string} port - 端口号
 * @returns {boolean}
 */
export const validatePort = port => {
  const portNum = parseInt(port)
  return !isNaN(portNum) && portNum >= 1 && portNum <= 65535
}

/**
 * 验证URL
 * @param {string} url - URL
 * @returns {boolean}
 */
export const validateURL = url => {
  try {
    new URL(url)
    return true
  } catch {
    return false
  }
}

/**
 * 验证邮箱
 * @param {string} email - 邮箱
 * @returns {boolean}
 */
export const validateEmail = email => {
  const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
  return emailRegex.test(email)
}

/**
 * 获取文件扩展名
 * @param {string} filename - 文件名
 * @returns {string}
 */
export const getFileExtension = filename => {
  if (!filename) return ''
  const lastDot = filename.lastIndexOf('.')
  return lastDot !== -1 ? filename.substring(lastDot + 1).toLowerCase() : ''
}

/**
 * 获取文件名（不含扩展名）
 * @param {string} filename - 文件名
 * @returns {string}
 */
export const getFileNameWithoutExtension = filename => {
  if (!filename) return ''
  const lastDot = filename.lastIndexOf('.')
  return lastDot !== -1 ? filename.substring(0, lastDot) : filename
}

/**
 * 下载文件
 * @param {Blob|string} data - 文件数据或URL
 * @param {string} filename - 文件名
 */
export const downloadFile = (data, filename) => {
  const link = document.createElement('a')

  if (typeof data === 'string') {
    link.href = data
  } else {
    const url = window.URL.createObjectURL(data)
    link.href = url
  }

  link.download = filename
  document.body.appendChild(link)
  link.click()
  document.body.removeChild(link)

  if (typeof data !== 'string') {
    window.URL.revokeObjectURL(link.href)
  }
}

/**
 * 复制到剪贴板
 * @param {string} text - 要复制的文本
 * @returns {Promise<boolean>}
 */
export const copyToClipboard = async text => {
  try {
    if (navigator.clipboard && window.isSecureContext) {
      await navigator.clipboard.writeText(text)
      return true
    } else {
      // 降级方案
      const textArea = document.createElement('textarea')
      textArea.value = text
      textArea.style.position = 'fixed'
      textArea.style.left = '-999999px'
      textArea.style.top = '-999999px'
      document.body.appendChild(textArea)
      textArea.focus()
      textArea.select()
      const result = document.execCommand('copy')
      document.body.removeChild(textArea)
      return result
    }
  } catch (error) {
    console.error('复制失败:', error)
    return false
  }
}

/**
 * 获取设备类型
 * @returns {string}
 */
export const getDeviceType = () => {
  const ua = navigator.userAgent
  if (/(tablet|ipad|playbook|silk)|(android(?!.*mobi))/i.test(ua)) {
    return 'tablet'
  }
  if (
    /Mobile|Android|iP(hone|od)|IEMobile|BlackBerry|Kindle|Silk-Accelerated|(hpw|web)OS|Opera M(obi|ini)/.test(
      ua
    )
  ) {
    return 'mobile'
  }
  return 'desktop'
}

/**
 * 获取浏览器信息
 * @returns {Object}
 */
export const getBrowserInfo = () => {
  const ua = navigator.userAgent
  let browser = 'Unknown'
  let version = 'Unknown'

  if (ua.indexOf('Chrome') > -1) {
    browser = 'Chrome'
    version = ua.match(/Chrome\/(\d+)/)?.[1] || 'Unknown'
  } else if (ua.indexOf('Firefox') > -1) {
    browser = 'Firefox'
    version = ua.match(/Firefox\/(\d+)/)?.[1] || 'Unknown'
  } else if (ua.indexOf('Safari') > -1) {
    browser = 'Safari'
    version = ua.match(/Version\/(\d+)/)?.[1] || 'Unknown'
  } else if (ua.indexOf('Edge') > -1) {
    browser = 'Edge'
    version = ua.match(/Edge\/(\d+)/)?.[1] || 'Unknown'
  }

  return { browser, version }
}

/**
 * 显示成功消息
 * @param {string} message - 消息内容
 */
export const showSuccess = message => {
  ElMessage.success(message)
}

/**
 * 显示错误消息
 * @param {string} message - 消息内容
 */
export const showError = message => {
  ElMessage.error(message)
}

/**
 * 显示警告消息
 * @param {string} message - 消息内容
 */
export const showWarning = message => {
  ElMessage.warning(message)
}

/**
 * 显示信息消息
 * @param {string} message - 消息内容
 */
export const showInfo = message => {
  ElMessage.info(message)
}

/**
 * 显示通知
 * @param {string} title - 标题
 * @param {string} message - 消息内容
 * @param {string} type - 类型
 */
export const showNotification = (title, message, type = 'info') => {
  ElNotification({
    title,
    message,
    type,
    duration: 4500
  })
}

/**
 * 确认对话框
 * @param {string} message - 消息内容
 * @param {string} title - 标题
 * @param {Object} options - 选项
 * @returns {Promise<boolean>}
 */
export const confirm = (message, title = '确认', options = {}) => {
  return ElMessageBox.confirm(message, title, {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning',
    ...options
  })
    .then(() => true)
    .catch(() => false)
}

/**
 * 提示对话框
 * @param {string} message - 消息内容
 * @param {string} title - 标题
 * @param {Object} options - 选项
 * @returns {Promise<string>}
 */
export const prompt = (message, title = '输入', options = {}) => {
  return ElMessageBox.prompt(message, title, {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    ...options
  })
    .then(({ value }) => value)
    .catch(() => null)
}

/**
 * 等待指定时间
 * @param {number} ms - 毫秒数
 * @returns {Promise}
 */
export const sleep = ms => {
  return new Promise(resolve => setTimeout(resolve, ms))
}

/**
 * 重试函数
 * @param {Function} fn - 要重试的函数
 * @param {number} retries - 重试次数
 * @param {number} delay - 延迟时间
 * @returns {Promise}
 */
export const retry = async (fn, retries = 3, delay = 1000) => {
  try {
    return await fn()
  } catch (error) {
    if (retries > 0) {
      await sleep(delay)
      return retry(fn, retries - 1, delay)
    }
    throw error
  }
}

/**
 * 获取查询参数
 * @param {string} name - 参数名
 * @returns {string|null}
 */
export const getQueryParam = name => {
  const urlParams = new URLSearchParams(window.location.search)
  return urlParams.get(name)
}

/**
 * 设置查询参数
 * @param {Object} params - 参数对象
 */
export const setQueryParams = params => {
  const url = new URL(window.location)
  Object.keys(params).forEach(key => {
    if (params[key] !== null && params[key] !== undefined) {
      url.searchParams.set(key, params[key])
    } else {
      url.searchParams.delete(key)
    }
  })
  window.history.replaceState({}, '', url)
}

/**
 * 清除查询参数
 */
export const clearQueryParams = () => {
  const url = new URL(window.location)
  url.search = ''
  window.history.replaceState({}, '', url)
}
